 import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.net.*;
 import java.text.DecimalFormat;
/**
 * Copyright 2011 Nick Stanish, Nathan Reynolds, Jeff Gough
 * this program is distributed under the terms of the GNU General Public License v3
 *
 */
 public class PS extends Applet implements Runnable, MouseListener,MouseMotionListener
{		DecimalFormat d3Form = new DecimalFormat("#.###"); //3 dec
        DecimalFormat d2Form = new DecimalFormat("#.##"); //2 dec
        DecimalFormat integer = new DecimalFormat("#"); //integer
        public String fps = "0 fps";
        public String error = "";
        public String Height;
        public double finalVelocity = 0;
        public double time = 0.000;
        public double refresh = .033;
        public double gravity = 9.8;
        public boolean originalPaint = false;
        public boolean platform = false;
        public boolean go = false;
        public int height = 150;
        public int refreshRate = Integer.valueOf(integer.format(refresh * 1000)); //convert to integer for timer in mseconds
        public int traveledDist = 0;
        public int velocity = 0;
        public int shape = 20;
        public int ground = 550;
        private Image mImage;
        public Image background;
		public Image Ball;
		public Image Start;
        public Image StopButton;
        javax.swing.Timer refreshTimer = new javax.swing.Timer(refreshRate, new ActionListener() {
		          public void actionPerformed(ActionEvent e) {
		              if (traveledDist + height >= ground){
                  traveledDist = ground - height; //if on ground then stops and leaves on ground
              Stop();
              repaint();
              }
              else{
              time = time + refresh; //calculates timer
              time = Double.valueOf(d3Form.format(time)); // 3 decimal sig
              double dist = (velocity * time) + ((gravity * time * time) / 2); //acceleration equation
              dist = dist / 2;
              traveledDist = Integer.valueOf(integer.format(dist)); //convert to integer
              finalVelocity = velocity + (gravity * time); //final velocity equation
              finalVelocity = Double.valueOf(d2Form.format(finalVelocity)); //2 decimal format
              if (finalVelocity < 0){ //if negative velocity then
                  finalVelocity = 0 - finalVelocity; //makes positive
                 }

		              repaint();
		              }
		          }
       });
       public void Stop(){
	               go = false;
	               fps = "0 fps";
	               refreshTimer.stop();
	          }
	          public void reset(){
	              time = 0;
	              traveledDist = 0;
	              finalVelocity = 0;
	              Stop();
       }
	public void mouseClicked(MouseEvent e){
	 int mouseX = e.getPoint().x;
	 int mouseY = e.getPoint().y;
	 if (mouseX < 195 && mouseX > 150 && mouseY < 125 && mouseY > 100){
		 if (!go){
	                fps = refreshRate + " fps";
	                go = true;
	                refreshTimer.start();
	                }
	                else {
	                Stop();
	                }
	                }
	                if (mouseX < 245 && mouseX > 200 && mouseY < 125 && mouseY > 100){
	                reset();
	                }
	                if(mouseX<175 && mouseX>160 && mouseY>180 && mouseY<195){
	                velocity = velocity - 10;
	                }
	                if(mouseX<195 && mouseX>180 && mouseY>180 && mouseY<195){
	                velocity--;
	                }
	                if(mouseX<265 && mouseX>250 && mouseY>180 && mouseY<195){
	             	velocity++;
	            	}
	         	if(mouseX<285 && mouseX>270 && mouseY>180 && mouseY<195){
	            	velocity = velocity + 10;
	        	 }

            repaint();
	}
	public void mouseExited(MouseEvent e){

	}
	public void mousePressed(MouseEvent e){
	int mouseX = e.getPoint().x;
	            int mouseY = e.getPoint().y;
	            if (mouseY > (height - 4) && mouseY < (height + 4) && mouseX < 80 && mouseX > 30){
	                platform = true;
                } //draggin platform
	}
	public void mouseReleased(MouseEvent e){
	 if (platform){
	                platform = false;
	                height = e.getPoint().y;
	                if ( height < 1) {
	                    height = 0;
	                }
	                if (height >= ground){
	                    height = ground;
	                }
	                } //dragging platform
                 repaint();
	}
	public void mouseMoved(MouseEvent e){

	}
	public void mouseDragged(MouseEvent e){

	}
	public void mouseEntered(MouseEvent e){

	}
	public void init()
	{	addMouseListener(this);
		addMouseMotionListener(this);
		setBackground (Color.lightGray);
		background = getImage (getCodeBase (), "media/background.png");
		Ball = getImage (getCodeBase (), "media/Ball.png");
		Start = getImage (getCodeBase (), "media/Start.png");
        StopButton = getImage (getCodeBase (), "media/Stop.png");
	}

	public void start ()
	{
		Thread th = new Thread (this);
		th.start ();
	}

	public void stop()
	{

	}

	public void destroy()
	{

	}

	public void run ()
	{
		Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

		while (true)
		{

			repaint();

			try
			{
				Thread.sleep (20);
			}
			catch (InterruptedException ex)
			{
				// do nothing
			}

			Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
		}
	}

	public void update (Graphics g)
	{
		paint(g);
	}

	public void paint (Graphics g)
	{
		 Dimension d = getSize(); //gets size of container
		 checkOffscreenImage(); //finds the painted off screen image
		 Graphics offG = mImage.getGraphics(); //create a graphic
		 offG.setColor(getBackground());
		 offG.fillRect(0, 0, d.width, d.height);
		    // Draw into the offscreen image.
		 paintOffscreen(mImage.getGraphics());
		    // Put the offscreen image on the screen.
   		 g.drawImage(mImage, 0, 0, null);
	}
	private void checkOffscreenImage() {
	    Dimension d = getSize();
	    if (mImage == null || mImage.getWidth(null) != d.width
	        || mImage.getHeight(null) != d.height) {
	      mImage = createImage(d.width, d.height);
	    }
	  }

	  public void paintOffscreen(Graphics g) {
		g.drawString("Click to Initiate", 180, 500);
        g.drawImage(background, 0, 0, null);
        if (go){
        g.drawImage(StopButton, 150, 100, null);
  		}
  		else{
        g.drawImage(Start, 150, 100, null);
 	   }
        g.drawImage(Ball, 80, (height - shape + traveledDist), null);

			Height = ((ground - height) * 2) + " m";
            g.setColor(Color.BLACK);
            g.drawString(Height, 40, 570);
            g.drawLine(30,ground, 30, height); //line to platform
            g.drawLine(30,height, 80, height); //platform
            g.drawString(time + " s", 180, 155);
            g.drawString(velocity + " m/s",200,195);
            g.drawString("initial velocity", 180, 210);
            g.drawString(finalVelocity + " m/s", 100, ground + 20); //m/s counter
            g.drawString(fps,170,ground + 20);
            g.drawString(error, 50,ground + 40);
        }
}